package de.jmda.gen.java.impl;

import java.util.ArrayList;
import java.util.List;

import de.jmda.gen.Generator;
import de.jmda.gen.GeneratorException;
import de.jmda.gen.impl.AbstractCompoundGenerator;
import de.jmda.gen.java.DeclaredFieldGenerator;
import de.jmda.gen.java.FieldModifiersGenerator;
import de.jmda.gen.java.FieldNameGenerator;
import de.jmda.gen.java.InitialisationGenerator;
import de.jmda.gen.java.TypeNameGenerator;

/**
 * @author rwegner
 */
public abstract class AbstractDeclaredFieldGenerator
		extends AbstractCompoundGenerator
		implements DeclaredFieldGenerator
{
	private FieldModifiersGenerator modifiersGenerator;
	private TypeNameGenerator typeNameGenerator;
	private FieldNameGenerator fieldNameGenerator;
	private InitialisationGenerator initialisationGenerator;

	public AbstractDeclaredFieldGenerator()
  {
	  this(null, null, null, null);
  }

	/**
	 * Sets component separator for component generation process to <code>" "
	 * </code>.
	 *
	 * @param modifiersGenerator
	 * @param typeNameGenerator
	 * @param fieldNameGenerator
	 * @param initialisationGenerator
	 */
	public AbstractDeclaredFieldGenerator(
      FieldModifiersGenerator modifiersGenerator,
      TypeNameGenerator typeNameGenerator,
      FieldNameGenerator fieldNameGenerator,
      InitialisationGenerator initialisationGenerator)
  {
	  super();

		setComponentSeparator(" ");

		if (modifiersGenerator == null)
		{
			this.modifiersGenerator = new DefaultFieldModifiersGenerator();
		}
		else
		{
			this.modifiersGenerator = modifiersGenerator;
		}

		if (typeNameGenerator == null)
		{
			this.typeNameGenerator = new DefaultTypeNameGenerator();
		}
		else
		{
			this.typeNameGenerator = typeNameGenerator;
		}

	  if (fieldNameGenerator == null)
	  {
			this.fieldNameGenerator = new DefaultFieldNameGenerator();
		}
		else
		{
			this.fieldNameGenerator = fieldNameGenerator;
		}

		if (initialisationGenerator == null)
		{
			this.initialisationGenerator = new DefaultInitialisationGenerator();
		}
		else
		{
			this.initialisationGenerator = initialisationGenerator;
		}
  }

	/**
	 * Returns collection of <code>Generator</code>s with the return values of the
	 * following methods in the following order:
	 * <ul>
	 *   <li>{@link #getModifiersGenerator()}</li>
	 *   <li>{@link #getTypeNameGenerator()}</li>
	 *   <li>{@link #getFieldNameGenerator()}</li>
	 *   <li>{@link #getInitialisationGenerator()}</li>
	 * </ul>
	 *
	 * @see de.jmda.gen.CompoundGenerator#getGeneratorComponents()
	 */
	@Override
	public List<Generator> getGeneratorComponents()
	{
		List<Generator> result = new ArrayList<Generator>();

		result.add(getModifiersGenerator());
		result.add(getTypeNameGenerator());
		result.add(getFieldNameGenerator());
		result.add(getInitialisationGenerator());
		// do not add generator for ";" here because it would result in generation
		// of blank + ";"
		// override getOutput() and generate() instead

		return result;
	}

	/**
	 * Appends <code>";"</code> to the result of <code>super.generate()</code>.
	 *
	 * @see de.jmda.gen.impl.AbstractCompoundGenerator#generate()
	 */
	@Override
  public StringBuffer generate() throws GeneratorException
  {
	  return super.generate().append(";");
  }

	/**
	 * @return {@link #modifiersGenerator}, may be <code>null</code> because
	 *         modifiers are optional.
	 *
	 * @see de.jmda.gen.java.DeclaredFieldGenerator#getModifiersGenerator()
	 */
	@Override
  public FieldModifiersGenerator getModifiersGenerator()
  {
		return modifiersGenerator;
  }

	@Override
  public FieldModifiersGenerator demandModifiersGenerator()
  {
		modifiersGenerator = notNull(modifiersGenerator);
		return modifiersGenerator;
  }

	/**
	 * @see de.jmda.gen.java.DeclaredFieldGenerator#getTypeNameGenerator()
	 */
	@Override
  public TypeNameGenerator getTypeNameGenerator()
  {
		return typeNameGenerator;
  }

	/**
	 * @see de.jmda.gen.java.DeclaredFieldGenerator#getFieldNameGenerator()
	 */
	@Override
  public FieldNameGenerator getFieldNameGenerator()
  {
		return fieldNameGenerator;
  }

	/**
	 * @return {@link #initialisationGenerator}, may be <code>null</code> because
	 *         initialisation is optional.
	 *
	 * @see de.jmda.gen.java.DeclaredFieldGenerator#getInitialisationGenerator()
	 */
	@Override
  public InitialisationGenerator getInitialisationGenerator()
  {
		return initialisationGenerator ;
  }

	/**
	 * noop for <code>null</code> parameter
	 *
	 * @see de.jmda.gen.java.DeclaredMethodGenerator#setModifiersGenerator(de.jmda.gen.java.MethodModifiersGenerator)
	 */
	@Override
	public void setModifiersGenerator(FieldModifiersGenerator generator)
	{
		if (generator == null)
		{
			return;
		}

		this.modifiersGenerator = generator;
	}
	
	/**
	 * noop for <code>null</code> parameter
	 *
	 * @see de.jmda.gen.java.DeclaredFieldGenerator#setTypeNameGenerator(de.jmda.gen.java.TypeNameGenerator)
	 */
	@Override
	public void setTypeNameGenerator(TypeNameGenerator generator)
	{
		if (generator == null)
		{
			return;
		}

	  this.typeNameGenerator = generator;
	}
	
	/**
	 * noop for <code>null</code> parameter
	 *
	 * @see de.jmda.gen.java.DeclaredFieldGenerator#setFieldNameGenerator(de.jmda.gen.java.FieldNameGenerator)
	 */
	@Override
	public void setFieldNameGenerator(FieldNameGenerator generator)
	{
		if (generator == null)
		{
			return;
		}

	  this.fieldNameGenerator = generator;
	}
	
	/**
	 * noop for <code>null</code> parameter
	 *
	 * @see de.jmda.gen.java.DeclaredFieldGenerator#setInitialisationGenerator(de.jmda.gen.java.InitialisationGenerator)
	 */
	@Override
	public void setInitialisationGenerator(InitialisationGenerator generator)
	{
		if (generator == null)
		{
			return;
		}

		this.initialisationGenerator = generator;
	}

	protected static FieldModifiersGenerator notNull(
			FieldModifiersGenerator generator)
  {
		if (generator == null)
		{
			generator = new DefaultFieldModifiersGenerator();
		}

		return generator;
  }
}